#include "TaskQueue.h"
#include "SyncQueue.h"
#include <map>

typedef std::lock_guard<std::mutex> locker;

CTaskQueue* CTaskQueue::m_pInstance = NULL;

CTaskQueue::CTaskQueue()
{
    m_TransId = 1;
    m_TaskQueue.clear();
 
    m_MainAcsStatus =  -1; //this status means, thread no started
    m_SlaveAcsStatus = -1; //this status means, thread no started

    char ConIniPath[256] = {0};
    snprintf(ConIniPath, sizeof(ConIniPath), "%s/config.ini", CONFIGFILEPATH);
    if(access(ConIniPath, F_OK) < 0)
    {
        strcpy(ConIniPath, "./config.ini");
    }

    m_CmsRole = 3;
    m_CmsRealRole = m_CmsRole;
}

CTaskQueue::~CTaskQueue()
{
    //dtor
}

CTaskQueue* CTaskQueue::GetInstance()
{
    if(m_pInstance == NULL)
    {
        static std::once_flag oc;
        std::call_once(oc, [&]()
            {
                m_pInstance = new CTaskQueue();
            }
        );
    }
    return m_pInstance;
}

void CTaskQueue::SetAcsStatus(bool bMain, int stauts)
{
    // -1未启动 0宕机 1等待 2活动 3备用 4失步 5单机
    bMain ? m_MainAcsStatus = stauts : m_SlaveAcsStatus = stauts;
}

int  CTaskQueue::GetAcsStatus(bool bMain)
{
    return bMain ? m_MainAcsStatus : m_SlaveAcsStatus;
}

int CTaskQueue::GetAcsStatus(int &mainstatus, int &slavestatus)
{
    int iStatus = 1;
    mainstatus = m_MainAcsStatus;
    slavestatus = m_SlaveAcsStatus;
    if ((mainstatus == -1 && slavestatus == 5) ||
        (mainstatus == -1 && slavestatus == 4) ||
        (mainstatus == 0 && slavestatus == 4) ||
        (mainstatus == 3 && slavestatus == 2) ||
        (mainstatus == 2 && slavestatus == 3) ||
        (mainstatus == 4 && slavestatus == 0) ||
        (mainstatus == 4 && slavestatus == -1) ||
        (mainstatus == 5 && slavestatus == -1)
        )
    {
        iStatus = 1; //normal status
    }
    else if ((mainstatus == 2 && slavestatus == 2) ||
        (mainstatus == 3 && slavestatus == 3) ||
        (mainstatus == 4 && slavestatus == 4) ||
        (mainstatus == 5 && slavestatus == 5)
        )
    {
        iStatus = 2; //abnormal status
    }
    else
    {  
        iStatus = 3; //temporary status...
    }
    return iStatus;
}

bool CTaskQueue::IsAcsActive(bool bMain, int &mainstatus, int &slavestatus)
{
    mainstatus = m_MainAcsStatus;
    slavestatus = m_SlaveAcsStatus;
    if(bMain)
    {
        if ((mainstatus == 2 && slavestatus == 3) ||
            (mainstatus == 4 && slavestatus == 0) ||
            (mainstatus == 5 && slavestatus == -1) ||
            (mainstatus == 4 && slavestatus == -1) ||
            (mainstatus == 2 && slavestatus == 0)
            )
        {
            return true;
        }
    }
    else
    {
        if ((slavestatus == 2 && mainstatus == 3) ||
            (slavestatus == 4 && mainstatus == 0) ||
            (slavestatus == 5 && mainstatus == -1) ||
            (slavestatus == 4 && mainstatus == -1) ||
            (slavestatus == 2 && mainstatus == 0)
            )
        {
            return true;
        }
    }
    
    return false;
}

unsigned int CTaskQueue::GetTransId()
{
    locker lock(m_mutex);
    if(4294967295 == m_TransId)
    {
        m_TransId = 1;
    }
    return m_TransId++;
}

void CTaskQueue::AddTask(uint64_t tranid, MsgPtr data)
{
    locker lock(m_mutex);
    if(m_TaskQueue.find(tranid) == m_TaskQueue.end())
    {
        m_TaskQueue.insert({ tranid, data });
    }
    else
    {
        LOG2(INFO, 
            "Add task to queue failed, tranid is already existing, id = %lu", 
            tranid
        );
    }
}

void CTaskQueue::DelTask(uint64_t tranid)
{
    locker lock(m_mutex);
    m_TaskQueue.erase(tranid);
}

bool CTaskQueue::FindTask(uint64_t tranid)
{
    locker lock(m_mutex);
    return m_TaskQueue.find(tranid) != m_TaskQueue.end();
}

MsgPtr CTaskQueue::GetTask(uint64_t tranid)
{
    locker lock(m_mutex);

    auto it = m_TaskQueue.find(tranid);
    if(it != m_TaskQueue.end())
    {
        return it->second;
    }

    return NULL;
}

MsgPtr CTaskQueue::GetTask(uint64_t tranid, BasicDataPtr remote, uint64_t task_id)
{
    locker lock(m_mutex);

    auto it = m_TaskQueue.find(tranid);
    if (it != m_TaskQueue.end())
    {
        return it->second;
    }

    MsgPtr& retVal = m_TaskQueue[tranid];

    retVal.reset(new Msg());
    retVal->m_remote = remote;
    retVal->m_taskId = task_id;
    retVal->m_recv_pack_index = 1;

    return retVal;
}

int CTaskQueue::GetSize()
{
    locker lock(m_mutex);
    return m_TaskQueue.size();
}

void CTaskQueue::RemoveTask(uint64_t tranid)
{
    locker lock(m_mutex);
    
    auto iter = m_TaskQueue.find(tranid);
    if (m_TaskQueue.end() == iter)
    {
        return;
    }

    if (NULL != iter->second->m_pDynamicBuf)
    {
        delete[] iter->second->m_pDynamicBuf.load();
        iter->second->m_pDynamicBuf = NULL;
    }

    m_TaskQueue.erase(iter);
}
